﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;

/// csis reference System.dll
/// csis reference System.Core.dll
/// csis reference System.Windows.Forms.dll
/// csis reference System.Drawing.dll

namespace ScriptHelpers
{
	public class FileDialogFilter
	{
		public FileDialogFilter(string filter, string description)
		{
			if (String.IsNullOrEmpty(filter))
			{
				filter = "*";
			}
			this.Filter = filter;
			this.Description = description;
		}

		public string Filter { get; private set; }
		public string Description { get; private set; }

		public string GetFormatted()
		{
			return String.Format("{0} ({1})|{1}", this.Description, this.Filter);
		}
	}

	public class FileDialog
	{
		public FileDialog()
		{
			this.Filters = new List<FileDialogFilter>();
		}

		public static string ShowOpenFileDialog(string title, string initialDirectory, params FileDialogFilter[] filters)
		{
			var dialog = new FileDialog();

			dialog.Title = title;
			dialog.InitialDirectory = initialDirectory;
			dialog.Filters.AddRange(filters);

			dialog.ShowDialog();
			return dialog.FileName;
		}

		public static string[] ShowMultiselectOpenFileDialog(string title, string initialDirectory, params FileDialogFilter[] filters)
		{
			var dialog = new FileDialog();

			dialog.Multiselect = true;
			dialog.Title = title;
			dialog.InitialDirectory = initialDirectory;
			dialog.Filters.AddRange(filters);

			dialog.ShowDialogInternal();
			return dialog.MultiselectFileNames;
		}

		public static string ShowSaveFileDialog(string title, string initialDirectory, params FileDialogFilter[] filters)
		{
			var dialog = new FileDialog();

			dialog.IsSaveDialog = true;
			dialog.Title = title;
			dialog.InitialDirectory = initialDirectory;
			dialog.Filters.AddRange(filters);

			dialog.ShowDialog();
			return dialog.FileName;
		}

		public void ShowDialog()
		{
			var thread = new Thread(this.ShowDialogInternal);
			thread.SetApartmentState(ApartmentState.STA);
			thread.IsBackground = true;
			thread.Start();
			thread.Join();
		}

		public bool IsSaveDialog { get; set; }
		public bool Multiselect { get; set; }
		public string InitialDirectory { get; set; }
		public string Title { get; set; }

		public List<FileDialogFilter> Filters { get; private set; }

		public string FileName { get; private set; }
		public string[] MultiselectFileNames { get; private set; }

		private string GetFiltersFormatted()
		{
			return String.Join("|", this.Filters.Select(x => x.GetFormatted()));
		}

		private void ShowDialogInternal()
		{
			System.Windows.Forms.FileDialog dialog;
			if (this.IsSaveDialog)
			{
				dialog = new System.Windows.Forms.SaveFileDialog();
			}
			else
			{
				var openFileDialog = new System.Windows.Forms.OpenFileDialog();
				openFileDialog.Multiselect = this.Multiselect;
				dialog = openFileDialog;
			}

			try
			{
				dialog.RestoreDirectory = true;
				dialog.Title = this.Title;
				dialog.Filter = this.GetFiltersFormatted();
				dialog.InitialDirectory = this.InitialDirectory;

				var result = dialog.ShowDialog();
				if (result != System.Windows.Forms.DialogResult.OK)
				{
					return;
				}

				if (this.Multiselect)
				{
					this.MultiselectFileNames = dialog.FileNames;
				}
				else
				{
					this.FileName = dialog.FileName;
				}
			}
			finally
			{
				dialog.Dispose();
			}
		}
	}

	public class FolderDialog
	{
		public FolderDialog()
		{

		}

		public static string ShowNew(string title, string initialDirectory)
		{
			var dialog = new FolderDialog();

			dialog.Title = title;
			dialog.InitialDirectory = initialDirectory;

			dialog.ShowDialog();

			return dialog.SelectedFolder;
		}

		public string SelectedFolder { get; private set; }

		public void ShowDialog()
		{
			var thread = new Thread(this.ShowDialogInternal);
			thread.SetApartmentState(ApartmentState.STA);
			thread.IsBackground = true;
			thread.Start();
			thread.Join();
		}

		public string Title { get; set; }
		public string InitialDirectory { get; set; }

		private void ShowDialogInternal()
		{
			using (var dialog = new System.Windows.Forms.FolderBrowserDialog())
			{
				dialog.Description = this.Title;
				dialog.SelectedPath = this.InitialDirectory;
				dialog.ShowNewFolderButton = true;

				var result = dialog.ShowDialog();
				if (result != System.Windows.Forms.DialogResult.OK)
				{
					return;
				}

				this.SelectedFolder = dialog.SelectedPath;
			}
		}
	}

	public class TextWindow
	{
		public TextWindow()
		{
			this.form = new System.Windows.Forms.Form();
			this.textBox = new System.Windows.Forms.TextBox();
			textBox.Dock = System.Windows.Forms.DockStyle.Fill;
			textBox.Multiline = true;
			textBox.BorderStyle = System.Windows.Forms.BorderStyle.None;
			form.Controls.Add(textBox);
		}

		private System.Windows.Forms.Form form;
		private System.Windows.Forms.TextBox textBox;

		public static TextWindow ShowNew(string title, string text, bool readOnly)
		{
			var window = new TextWindow();

			window.Title = title;
			window.Text = text;
			window.ReadOnly = readOnly;

			window.Show();

			return window;
		}

		public static TextWindow ShowNew(string title, string text, bool readOnly, bool monospace)
		{
			if (monospace)
			{
				return ShowNew(title, text, readOnly, System.Drawing.FontFamily.GenericMonospace.Name, 10, false, false);
			}
			else
			{
				return ShowNew(title, text, readOnly);
			}
		}

		public static TextWindow ShowNew(string title, string text, bool readOnly, string font, double fontSize, bool bold, bool italic)
		{
			var window = new TextWindow();

			window.Title = title;
			window.Text = text;
			window.ReadOnly = readOnly;

			window.SetFont(font, fontSize, bold, italic);

			window.Show();

			return window;
		}

		public void SetFont(string font, double fontSize, bool bold, bool italic)
		{
			System.Drawing.FontStyle fontStyle = System.Drawing.FontStyle.Regular;
			if (bold)
			{
				fontStyle |= System.Drawing.FontStyle.Bold;
			}
			if (italic)
			{
				fontStyle |= System.Drawing.FontStyle.Italic;
			}

			this.textBox.Font = new System.Drawing.Font(font, (float)fontSize, fontStyle);
		}

		public string Text
		{
			get { return this.textBox.Text; }
			set { this.textBox.Text = value; }
		}

		public string Title
		{
			get { return this.form.Text; }
			set { this.form.Text = value; }
		}

		public bool ReadOnly
		{
			get { return this.textBox.ReadOnly; }
			set { this.textBox.ReadOnly = value; }
		}

		public void Show()
		{
			System.Windows.Forms.Application.Run(this.form);
		}

		public void Close()
		{
			this.form.Close();
		}
	}
}
